/*
 *  您可以更改此项目但请不要删除作者署名谢谢，否则根据中华人民共和国版权法进行处理.
 *  You may change this item but please do not remove the author's signature,
 *  otherwise it will be dealt with according to the Copyright Law of the People's Republic of China.
 *
 *  如果需要联系到我请加Wechat: yangbuyiya 备注交流学习
 *  If you need to contact me, please add Wechat: yangbuyiya as a note to exchange and learn.
 *  yangbuyi Copyright (c) https://yby6.com 2024.
 */

package com.yby6.utils;


import com.tencent.SpeechClient;
import com.tencent.asr.model.Credential;
import com.tencent.asr.model.FlashRecognitionRequest;
import com.tencent.asr.model.FlashRecognitionResponse;
import com.tencent.asr.service.FlashRecognizer;
import com.yby6.config.TencentConfig;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.core.handle.DownloadedFile;
import org.noear.solon.core.handle.UploadedFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;


/**
 * 录音文件识别极速版本 - 工具类
 *
 * @author Yang Shuai
 * Create By 2024/06/14
 */
@Slf4j
public class AsrUtils {
    private static final Credential credential = initCredential();
    private static final FlashRecognizer recognizer = initRecognizer();
    private static final FlashRecognitionRequest recognitionRequest = initRecognitionRequest();

    /**
     * 初始化凭证
     *
     * @return {@link Credential}
     */
    private static Credential initCredential() {
        TencentConfig instance = TencentConfig.getInstance();
        return Credential.builder()
                .secretId(instance.getSecretId())
                .secretKey(instance.getSecretKey())
                .build();
    }

    /**
     * 初始化识别器
     *
     * @return {@link FlashRecognizer}
     */
    private static FlashRecognizer initRecognizer() {
        TencentConfig instance = TencentConfig.getInstance();
        return SpeechClient.newFlashRecognizer(instance.getAppId(), credential);
    }

    /**
     * 初始化识别请求
     *
     * @return {@link FlashRecognitionRequest}
     */
    private static FlashRecognitionRequest initRecognitionRequest() {
        FlashRecognitionRequest request = FlashRecognitionRequest.initialize();
        request.setEngineType("16k_zh"); // 引擎类型
        request.setFirstChannelOnly(1); // 单声道
        request.setVoiceFormat("ogg-opus"); // 语音格式
        request.setSpeakerDiarization(0); // 说话人分离
        request.setFilterDirty(0); // 过滤脏话
        request.setFilterModal(0); // 过滤语气词
        request.setFilterPunc(0); // 过滤标点
        request.setConvertNumMode(1); // 数字转换
        request.setWordInfo(1); // 词级别结果
        return request;
    }


    /**
     * 语音转文本快速版
     *
     * @param data 语音文件流
     * @return {@link FlashRecognitionResponse}
     */
    public static FlashRecognitionResponse voiceToTextSpeedEdition(DownloadedFile data) {
        try {
        
            FlashRecognitionResponse recognize = recognizer.recognize(recognitionRequest, getBytes(data));
            Long audioDuration = recognize.getAudioDuration();
            // audioDuration  四舍五入计算 不保留小数 正数
            BigDecimal videoDuration = BigDecimal.valueOf(audioDuration)
                    .divide(BigDecimal.valueOf(1000), 0, RoundingMode.HALF_UP);
            recognize.setAudioDuration(videoDuration.longValue());
            return recognize;
        } catch (Exception e) {
            log.error("录音文件识别极速版识别异常: {}", e.getMessage());
            throw new RuntimeException("录音文件识别失败", e);
        }
    }
    
    public static byte[] getBytes(DownloadedFile uploadedFile) throws IOException {
        try (InputStream content = uploadedFile.getContent();
             ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
            
            byte[] data = new byte[4096];  // 使用较大的缓冲区提高性能
            int nRead;
            
            while ((nRead = content.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, nRead);
            }
            
            return buffer.toByteArray();
        }
    }

}
